﻿using AutoMapper;
using Enter.Admin.Dtoes;
using Enter.Admin.Entities;
using Enter.Admin.Enums;
using Enter.Admin.Filters;
using Enter.Admin.Models;
using Enter.Admin.Models.DataTables;
using Enter.Admin.Utils;
using FluentValidation.AspNetCore;
using FreeSql;
using FreeSql.Internal.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace Enter.Admin.Controllers
{
    [TypeFilter(typeof(ActionFilter))]
    public class HomeController : BaseController
    {
        // private readonly IServiceProvider _provider; //_provider.GetService<IMapper>();
        private readonly Upload _upload;
        private readonly Mail _mail;
        private readonly IConfiguration _configuration;

        public HomeController(ILogger<HomeController> logger, IFreeSql fsql, IMapper mapper, Upload upload, Mail mail, IConfiguration configuration) :base(logger, fsql, mapper)
        {
            _upload = upload;
            _mail = mail;
            _configuration = configuration;
        }

        public IActionResult Index(long id)
        {
            // id 是TableId
            var tables = _fsql.Select<DynamicTable>()
                //.IncludeMany(t => t.Columns)
                .Where(t => t.TableName == nameof(Archive)).ToList();

            var model = new HomeIndexModel
            {
                TableId = id,
                Tables = tables,
                Columns = columns(id),
            };
            return View(model);
        }

        [HttpPost]
        public ActionResult Columns(long id)
        {
            return Json(new ResponseResult<List<DataTablesColumn>>(true, columns(id), "ok."));
        }

        private List<DataTablesColumn> columns(long tableId) 
        {
            var columns = DataTablesColumnExt.ToList<ArchiveModel>();
            if (tableId == 0) {
                return columns;
            }
            var all_columns = _mapper.Map<List<DataTablesColumn>>(columns);
            var new_columns = new List<DataTablesColumn>();
            var cs = _fsql.Select<DynamicColumn>().Where(t => t.TableId == tableId).ToList();
            foreach (var v in cs) 
            {
                var find = all_columns.Where(t => t.data == v.ColumnName).First();
                find.visible = true;
                new_columns.Add(find);
            }

            all_columns.ForEach(t =>
            {
                if (!new_columns.Any(c => c.data == t.data)) 
                {
                    t.visible = false;
                    new_columns.Add(t);
                }
            });
            return new_columns;
        }

        //[Produces("application/json")]
        [HttpPost]
        // [ValidateAntiForgeryToken]
        public IActionResult LoadData([FromBody] DataTablesParameters<ArchiveSearchModel> model)
        {
            // https://docs.microsoft.com/zh-cn/aspnet/core/web-api/jsonpatch?view=aspnetcore-5.0
            var _select = SearchList(model.Data);
            var list = _select.OrderByDescending(t=>t.Id).Count(out var total).Skip(model.Start).Take(model.Length).ToList();
            var data = _mapper.Map<List<ArchiveModel>>(list);
            return Json(new DataTablesResult<ArchiveModel>(model.Draw, total, total, data));
        }

        private ISelect<Archive> SearchList(ArchiveSearchModel model)
        {
            //或者
            //_fsql.Select<Archive>().From<ArchiveTableMap>((a, map) => a.InnerJoin(t => t.Id == map.ArchiveId))
            //  .Where((a, map) => map.TableId == model.TableId)
            //  .WhereIf(model.Id > 0, b => b.t1.Id == model.Id)
            //  .ToList((a, map) => a);

            var _select = _fsql.Select<Archive>();
            if (model.TableId > 0) 
            {
                _select = _fsql.Select<Archive>().InnerJoin("ArchiveTableMap b on b.ArchiveId = a.Id and b.TableId = @TableId", new { TableId = model.TableId });
            }
            _select = _select.WhereIf(model.Id > 0, t => t.Id == model.Id)
             .WhereIf(!string.IsNullOrWhiteSpace(model.BusinessNo), t => t.BusinessNo == model.BusinessNo)
             .WhereIf(!string.IsNullOrWhiteSpace(model.ContractNo), t => t.ContractNo.Contains(model.ContractNo))
             .WhereIf(!string.IsNullOrWhiteSpace(model.CustomerID), t => t.CustomerID.Contains(model.CustomerID));

            var dynamicWhere = false;
            DynamicFilterInfo info = new DynamicFilterInfo();
            info.Logic = DynamicFilterLogic.And;
            info.Filters = new List<DynamicFilterInfo>();
            if (!string.IsNullOrWhiteSpace(model.SearchStringField) && !string.IsNullOrWhiteSpace(model.SearchStringValue))
            {
                info.Filters.Add(new DynamicFilterInfo { 
                    Field = model.SearchStringField.Trim(),
                    Value = model.SearchStringValue ,
                    Operator = model.SearchStringOperator,
                });
                dynamicWhere = true;
            }
            if (!string.IsNullOrWhiteSpace(model.SearchEnumField) && !string.IsNullOrWhiteSpace(model.SearchEnumValue) && model.SearchEnumValue != "0")
            {
                info.Filters.Add(new DynamicFilterInfo
                {
                    Field = model.SearchEnumField.Trim(),
                    Value = model.SearchEnumValue,
                    Operator = DynamicFilterOperator.Eq,
                });
                dynamicWhere = true;
            }
            if (!string.IsNullOrWhiteSpace(model.SearchDateField) && !string.IsNullOrWhiteSpace(model.SearchDateValue))
            {
                info.Filters.Add(new DynamicFilterInfo
                {
                    Field = model.SearchDateField.Trim(),
                    Value = model.SearchDateValue.Split(" - "),
                    Operator = DynamicFilterOperator.DateRange,
                });
                dynamicWhere = true;
            }
            if (dynamicWhere) 
            {
                _select.WhereDynamicFilter(info);
            }
            if (!string.IsNullOrWhiteSpace(model.FullText))
            {
                //DynamicFilterInfo
                _select.Where(t => t.ContractNo.Contains(model.FullText) || t.BatchNo.Contains(model.FullText));
            }
            return _select;
        }

        // GET: Home/Edit/5
        public ActionResult Edit(long id)
        {
            var session = Session();
            if (id == 0)
            {
                if (!session.Role.IsDefault) 
                {
                    return Content("没有权限.");
                }
                return View(new ArchiveModel());
            }
            var model = _fsql.Select<Archive>(new { Id = id }).ToOne();
            if (model == null || model.IsDeleted)
            {
                return View("Error", new ErrorViewModel() { StatusCode = 404 });
                // 404
            }
            return View(_mapper.Map<ArchiveModel>(model));
        }

        // POST: Home/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(long id, ArchiveModel model)
        {
            var session = Session();
            if (id == 0)
            {
                if (!session.Role.IsDefault)
                {
                    return Json(new ResponseResult<string>(false, "没有权限."));
                }
                var db_arc = _mapper.Map<Archive>(model);
                db_arc.CreateTime = DateTime.Now;
                db_arc.UpdateTime = DateTime.Now;
                db_arc.IsDeleted = false;
                var new_id = _fsql.Insert<Archive>(db_arc).ExecuteIdentity();//.ExecuteAffrows();
                db_arc.Id = new_id;
                if (new_id > 0)
                {
                    // 添加Item
                    Natural(db_arc);
                    return Json(new ResponseResult<string>(true, "新增成功."));
                }
                return Json(new ResponseResult<string>(false, "新增失败."));
            }
            else 
            {
                model.Id = id;
                var dbModel = _fsql.Select<Archive>(new { Id = id }).ToOne();
                _mapper.Map(model, dbModel);
                dbModel.UpdateTime = DateTime.Now;
                var count = _fsql.Update<Archive>().SetSource(dbModel).IgnoreColumns(new string[] { "CreateTime" }).ExecuteAffrows();//.SetSourceIgnore(dbModel, c => c == null)
                // 添加Item
                Natural(dbModel);
                if (count > 0)
                {
                    return Json(new ResponseResult<string>(true, "更新成功."));
                }
                return Json(new ResponseResult<string>(false, "更新失败."));
            }
            // https://www.cnblogs.com/FreeSql/p/11531327.html
            // https://www.cnblogs.com/FreeSql/p/11531321.html
            // https://www.cnblogs.com/FreeSql/p/11531334.html
        }

        // GET: Home/Detail/5
        public ActionResult Detail(long id)
        {
            return View(_fsql.Select<Archive>(new { Id = id }).ToOne());
        }

        [HttpPost]
        public ActionResult Allocation([FromBody]AllocationModel model) 
        {
            if (model.ArchiveIds.Count() < 1)
            {
                return Json(new ResponseResult<string>(false, "请选择需要分配的案件."));
            }
            else if (model.ChargeUserId<1) 
            {
                return Json(new ResponseResult<string>(false, "请选择负责人."));
            }
            var count = _fsql.Update<Archive>().Set(t => t.ChargeUserId2, model.ChargeUserId).Where(t=> model.ArchiveIds.Contains(t.Id)).ExecuteAffrows();
            return Json(new ResponseResult<string>(true, string.Format("成功分配案件数({0}).", count)));
        }

        [HttpPost]
        public ActionResult AllocationTable([FromBody] AllocationTableModel model)
        {
            if (model.ArchiveIds.Count() < 1)
            {
                return Json(new ResponseResult<string>(false, "请选择需要分配的案件."));
            }
            else if (model.TableId < 1)
            {
                return Json(new ResponseResult<string>(false, "请选择所属机构."));
            }

            foreach (var aid in model.ArchiveIds)
            {
                _fsql.InsertOrUpdate<ArchiveTableMap>().SetSource(new ArchiveTableMap {TableId=model.TableId,ArchiveId=aid }).ExecuteAffrows();
            }
            return Json(new ResponseResult<string>(true, "分配成功."));
        }

        [HttpPost]
        public ActionResult AllocationTableList([FromBody] AllocationTableListModel model)
        {
            if (model.TableId > 0 && model.ArchiveId >0)
            {
                if (model.IsDeleted)
                {
                    _fsql.Delete<ArchiveTableMap>().Where(t => t.TableId == model.TableId && t.ArchiveId == model.ArchiveId).ExecuteAffrows();
                }
                else
                {
                    _fsql.InsertOrUpdate<ArchiveTableMap>().SetSource(new ArchiveTableMap { TableId = model.TableId, ArchiveId = model.ArchiveId }).ExecuteAffrows();
                }
            }
            var data = _fsql.Select<ArchiveTableMap, DynamicTable>().InnerJoin((map, table) => map.TableId == table.Id)
               .Where((map, table) => map.ArchiveId == model.ArchiveId)
               .ToList((map, table) => new { map.TableId, map.ArchiveId, table.Name });
            return Json(new ResponseResult<object> (true, data, "ok."));
        }


        

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Upload(long id, IEnumerable<IFormFile> files)
        {
            if(files.Count()==0) return Json(new ResponseResult<string>(false, "请选择文件."));
            if (id == 0)
            {
                var file = files.First();
                if (!file.FileName.EndsWith(".xlsx"))
                {
                    return Json(new ResponseResult<string>(false, "不支持的文件类型."));
                }
                var new_file = FileIO.CreateFile(file.FileName, true);
                using (var stream = new_file.FileInfo.Create())
                {
                    file.CopyTo(stream);
                }
                return Json(new ResponseResult<string>(true, new_file.FileInfo.FullName, "上传成功."));
            }
            else 
            {
                var result = new List<long>();
                var session = Session();
                foreach (var form_file in files) 
                {
                    // 写入文件;
                    var new_file = FileIO.CreateFile(form_file.FileName, false);
                    using (var stream = new_file.FileInfo.Create())
                    {
                        form_file.CopyTo(stream);
                    }
                    // 写入数据库;
                    var db_att = new Attachment
                    {
                        ObjectType = (int)EnumAttachmentObjectType.档案附件,
                        ObjectId = id,
                        IsTemp = false,
                        CatalogType = 0,
                        Catalog = string.Empty,
                        Name = form_file.FileName,
                        PathName = new_file.PathName,
                        Extension = new_file.Extension,
                        FileSize = new_file.FileInfo.Length,
                        FileMD5 = FileIO.Md5(new_file.FileInfo),
                        // 同步文件;
                        IsSync = _upload.PutObject(new_file.PathName, new_file.FileInfo),
                        CreateUserId = session.Id,
                        CreateTime = DateTime.Now,
                        UpdateTime = DateTime.Now,
                        IsDeleted = false
                    };
                    var att_id = _fsql.Insert<Attachment>(db_att).ExecuteIdentity();
                    result.Add(att_id);
                }
                return Json(new ResponseResult<List<long>>(true, result, "上传成功."));
            }
        }

        [HttpPost]
        //[ValidateAntiForgeryToken]
        public ActionResult Import(string fileName)
        {
            var insertCount = 0;
            var updateCount = 0;
            var excelCount = 0;
            var excelTuple = Excel.ToList<ArchiveModel>(fileName, drops: EnumsExt.EnumMap);
            if (excelTuple.Errors.Count > 0) 
            {
                return Json(new ResponseResult<string>(false, string.Join(" ; ", excelTuple.Errors)));
            }
            // 判断合同编号是否重复
            var distinct_ContractNo = excelTuple.DataList.Select(t => t.ContractNo).GroupBy(p => p).Where(i => i.Count() > 1);
            if (distinct_ContractNo.Count() > 0)
            {
                if (distinct_ContractNo.Any(t => string.IsNullOrWhiteSpace(t.Key)))
                {
                    return Json(new ResponseResult<string>(false,
                        string.Format("读取到合同编号存在为空的情况(读取行数：{0},请检查是否匹配)", excelTuple.DataList.Count )
                    ));
                }
                return Json(new ResponseResult<string>(false,
                    string.Format("重复合同编号(读取行数：{0})：{1}",
                        excelTuple.DataList.Count,
                        string.Join(",", distinct_ContractNo.Select(t => t.Key))
                    )
                    ));
            }
            var session = Session();
            var repeat_all = new List<string>();
            _fsql.Transaction(() =>
            {
                foreach (var item in excelTuple.DataList)
                {
                    excelCount++;
                    Archive arc = null;
                    if (item.Id > 0) 
                    {
                        arc = _fsql.Select<Archive>(new { Id = item.Id }).ToOne();
                    }
                    if (arc == null && session.Role.IsDefault)
                    {
                        arc = _mapper.Map<Archive>(item);
                        arc.CreateTime = DateTime.Now;
                        arc.UpdateTime = DateTime.Now;
                        arc.IsDeleted = false;
                        if (arc.Id > 0)
                        {
                            insertCount += _fsql.Insert<Archive>(arc).ExecuteAffrows();
                        }
                        else
                        {
                            arc.Id = _fsql.Insert<Archive>(arc).ExecuteIdentity();
                            insertCount += 1;
                        }
                        //var i_c = _fsql.Insert<Archive>(arc).InsertColumns(insertColumns.ToArray()).ExecuteAffrows();
                        // 判断重复项;
                        var repeatCur = Repeat(arc);
                        if (repeatCur.Count>0) 
                        {
                            repeat_all.AddRange(repeatCur);
                        }
                    }
                    else
                    {
                        _mapper.Map(item, arc);
                        var updateColumns = excelTuple.ExcelColumns.Select(t => t.PropertyName).ToList();                       
                        updateColumns.Add(nameof(arc.UpdateTime));
                        arc.UpdateTime = DateTime.Now;
                        var u_c = _fsql.Update<Archive>().SetSource(arc).UpdateColumns(updateColumns.ToArray()).ExecuteAffrows();
                        updateCount += u_c;
                        //_fsql.Update<Archive>().SetSourceIgnore(arc, t => t == null).ExecuteAffrows();
                    }
                    // 添加Item
                    Natural(arc);
                }
            });
            var repeat_str = string.Empty;
            repeat_str = string.Join(",", repeat_all.Distinct());
            if (!string.IsNullOrWhiteSpace(repeat_str)) {
                repeat_str = string.Format(" ({0})", repeat_str);
            }
            return Json(new ResponseResult<string>(true, string.Format("导入成功. (Excel总数：{0}, 修改：{1}, 新增：{2}) {3}",excelCount,updateCount,insertCount, repeat_str)));
        }

        public ActionResult Export(long id)
        {
            var att = _fsql.Select<Attachment>(new { Id= id }).First();
            if (att == null || att.IsDeleted) 
            {
                return Content("文件不存在.");
            }
            var fileInfo = FileIO.GetFile(att.PathName);
            if (!fileInfo.Exists) 
            {
                if (att.IsTemp)
                {
                    return Content("文件不存在.");
                } 
                else
                {
                    if (!att.IsSync) 
                    {
                        return Content("文件不存在(未同步).");
                    }
                    // 飞临时文件则同步oss;
                    if (_upload.GetObject(att.PathName))
                    {
                        if(!fileInfo.Exists)
                            return Content("文件同步失败.");
                    }
                    else
                    {
                        return Content("文件同步下载失败.");
                    }
                }
            }
            return File(fileInfo.OpenRead(), new FileExtensionContentTypeProvider().Mappings[att.Extension], att.Name);
            //var _select = SearchList(model);
            ////var fileName = "";
            ////var addrUrl = fileName;
            ////var stream = System.IO.File.OpenRead(addrUrl); //Path.GetExtension
            ////string fileExt = Path.GetExtension(fileName);
            //////获取文件的ContentType
            ////var provider = new FileExtensionContentTypeProvider();
            ////var memi = provider.Mappings[fileExt];
            ////// var downloadName = Path.GetFileName(addrUrl);
            ////return File(stream, memi, "name.xlsx");
            //var list = _mapper.Map<List<ArchiveModel>>(_select.ToList());
            //var drops = new Dictionary<string, List<SelectListItem>>();
            //var users = _fsql.Select<Employ>().Where(t => t.IsDeleted == false).ToList()
            //.Select(t => new SelectListItem { Value = t.TrueName, Text = t.TrueName }).ToList();
            //drops.Add("Employ", users);
            //return File(Excel.Save(list, drops), new FileExtensionContentTypeProvider().Mappings[".xlsx"], "档案列表.xlsx");
        }

        [HttpPost]
        public ActionResult Export([FromBody]ArchiveExportModel model)
        {
            ISelect<Archive> _select;
            if (model.Rows.Count() > 0)
            {
                _select = _fsql.Select<Archive>().WhereDynamic(model.Rows);
            }
            else 
            {
                _select = SearchList(model.Data);
            }
            // 导出;
            var list = _mapper.Map<List<ArchiveModel>>(_select.OrderByDescending(t => t.Id).ToList());
            var name = "档案列表.xlsx";
            var file = FileIO.CreateFile(name, true);
            Excel.Save(file.FileInfo, list, model.Columns, EnumsExt.EnumMap);
            // 写入文件;
            var session = Session();
            var db_att = new Attachment{
                ObjectType = (int)EnumAttachmentObjectType.临时文件,
                ObjectId = 0,
                IsTemp = true,
                CatalogType = 0,
                Catalog = string.Empty,
                Name = name,
                PathName = file.PathName,
                Extension = file.Extension,
                FileSize = file.FileInfo.Length,
                FileMD5 = FileIO.Md5(file.FileInfo),
                IsSync = false,
                CreateUserId = session.Id,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now,
                IsDeleted = false
            };
            var att_id = _fsql.Insert<Attachment>(db_att).ExecuteIdentity();
            if(att_id>0)
                return Json(new ResponseResult<long>(true, att_id, "下载成功."));
            return Json(new ResponseResult<string>(false,  "下载失败."));
        }

        // 判断重复项;
        private List<string> Repeat(Archive archive)
        {
            var repeatList = new List<string>();
            {
                var hasRepeat = _fsql.Select<Archive>().Where(t => t.IsDeleted == false && t.CustomerID == archive.CustomerID).Count() > 1;
                if (hasRepeat)
                {
                    repeatList.Add(archive.CustomerID);
                }
            }
            {
                var hasRepeat = _fsql.Select<Archive>().Where(t => t.IsDeleted == false && t.CustomerName == archive.CustomerName).Count() > 1;
                if (hasRepeat)
                {
                    repeatList.Add(archive.CustomerName);
                }
            }
            return repeatList;
        }

        // 更新案件记载;
        private int Natural(Archive archive)
        {
            return 0;
            var year = DateTime.Now.Year;
            var item = _fsql.Select<ArchiveNatural>().Where(t => t.ArchiveId == archive.Id && t.NaturalYear == year).First();

            var update_item = _mapper.Map<ArchiveNatural>(archive);
            update_item.NaturalYear = year;
            update_item.ArchiveId = archive.Id;
            update_item.UpdateTime = DateTime.Now;

            if (item == null)
            {
                return _fsql.Insert<ArchiveNatural>(update_item).ExecuteAffrows();
            }
            else
            {
                return _fsql.Update<ArchiveNatural>().SetSource(update_item).ExecuteAffrows();
            }
        }

        [HttpPost]
        public ActionResult Natural(long id)
        {
            var data = _fsql.Select<ArchiveNatural>().Where(t => t.ArchiveId == id).ToList();
            return Json(new ResponseResult<List<ArchiveNaturalModel>>(true, _mapper.Map<List<ArchiveNaturalModel>>(data), "ok."));
        }

        [HttpGet]
        public ActionResult Natural(long archiveId, long naturalYear)
        {
            var data = _fsql.Select<ArchiveNatural>().Where(t => t.ArchiveId == archiveId && t.NaturalYear ==naturalYear).First();
            return Json(new ResponseResult<ArchiveNatural>(true, data, "ok."));
        }

        [HttpPost]
        public ActionResult NaturalSave(ArchiveNatural model)
        {
            model.UpdateTime = DateTime.Now;
           _fsql.Update<ArchiveNatural>().SetSource(model).ExecuteAffrows();
            return Json(new ResponseResult<string>(true, "ok."));
        }


        public ActionResult Profile()
        {
            return View(Session());
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Profile([CustomizeValidator(Properties = "Password",RuleSet = "default")] EmployModel model)
        {
            var session = Session();
            if (session != default)
            {
                _fsql.Update<Employ>()
                 .SetIf(!string.IsNullOrWhiteSpace(model.Password), a => a.Password, Crypto.Md5(model.Password))
                 .SetIf(!string.IsNullOrWhiteSpace(model.Email), a => a.Email, model.Email)
                 .SetIf(!string.IsNullOrWhiteSpace(model.Phone), a => a.Phone, model.Phone)
                 .Set(a => a.UpdateTime, DateTime.Now)
                 .Where(a => a.Id == session.Id).ExecuteAffrows();
                this.UpdateSession();
            }
            return Json(new ResponseResult<string>(true, "更新成功."));
        }
        public ActionResult Flush()
        {
            // 初始化;
            Controllers.BaseController.Init(_fsql, _configuration);
            return Content("Flush.");
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}
